﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using BTv2.Model;

namespace BTv2.Controls
{
    public class UsersController
    {
        private ObservableCollection<User> _users;
        private ObservableCollection<MailingList> _mlists;
        private static UsersController _instance;
        private DatabaseController _dbInstance;
        private User _loggedUser;
        public ObservableCollection<User> Users
        {
            get { return _users; }
        }

        public User GetLoggedUser()
        {

            return _loggedUser;
        }
        public ObservableCollection<MailingList> MLists
        {
            get { return _mlists; }
        }

        public static UsersController GetInstance()
        {
            if (_instance == null)
            {
                _instance = new UsersController();
            }
            return _instance;
        }

        public UsersController()
        {
            _dbInstance = DatabaseController.GetInstance();
        }

        public async Task<bool> ValidateUserCredentials(string username, string password)
        {
            string hpwd = User.GetMD5Hash(password);
            if(_users == null) _users = await _dbInstance.GetUsers();
            return _users.Any(user => user.UserName == username && user.Password == hpwd);
        }
        public async Task<string> GetLoggedUserID()
        {
            return _loggedUser.UserName;
        }

        public async Task<bool> UserLogged(string userName)
        {
            try
            {
                _loggedUser = _users.Where(user => user.UserName == userName).First();
                return true;
            }
            catch
            {
                return false;
            }
        }
        public async Task<bool> UserExsists(string userName)
        {
            if (_users == null) _users = await _dbInstance.GetUsers();
            return _users.Any(user => user.UserName == userName);
        }
        public async Task<bool> UserAdmin(string userName)
        {
            if (_users == null) _users = await _dbInstance.GetUsers();
            return _users.Where(user=>user.UserName == userName).First().IsAdmin;
        }

        public async Task<bool> PreloadUserList()
        {
            try
            {
                _users = await _dbInstance.GetUsers();
                return true;
            }
            catch
            {
                return false;
            }
        }
        public async Task<ObservableCollection<User>> GetFilteredUserList(MailingList ml)
        {
            return new ObservableCollection<User>(_users.Except(ml.Users));
        }

        public async Task<bool> PreloadMailingLists()
        {
            try
            {
                _mlists = await _dbInstance.GetMailingLists(_users);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> SaveMailingList(MailingList ml, string name, string description)
        {
            try
            {
           bool result= await _dbInstance.SaveMailingList(ml, name, description);
                return result;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeleteMailingList(MailingList ml)
        {
            try
            {
                return await _dbInstance.RemoveMailingList(ml);
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> AddUser(User u)
        {
            try
            {
               bool res1 = await _dbInstance.AddUser(u);
               if (!res1) return res1;
               int id = await _dbInstance.GetLastUserID();
               u.ID = id;
               return res1;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> DeleteUser(User u)
        {
            try
            {
                await _dbInstance.RemoveUser(u);
                foreach (var m in MLists)
                {
                    if (m.Users.Any(x => x.ID == u.ID))
                    {
                        Application.Current.Dispatcher.Invoke(() =>  m.Users.Remove(u));
                      
                    }
                }

                return true;
            }
            catch
            {
                return false;
            }
        }
        public async Task<bool> SaveUser(User u)
        {
            try
            {
                return await _dbInstance.SaveUser(u);
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> SendMail(User u, string Mailmessage)
        {
            try
            {
                var fromAddress = new MailAddress(Properties.Settings.Default.MailUserName, "BuildingTomorrow House");
                var toAddress = new MailAddress(u.Mail, u.UserName);
                string fromPassword = Properties.Settings.Default.MailPassword;
                string subject = "Important Message";
                string body = Mailmessage;

                var smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",
                    Port = 587,
                    EnableSsl = true,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
                };
                using (var message = new MailMessage(fromAddress, toAddress)
                {
                    Subject = subject,
                    Body = body
                })
                {
                    smtp.Send(message);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        public async Task<bool> SendErrorMail( string Mailmessage,string exceptionName, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null,[CallerLineNumber] int lineNumber = 0)
        {
            try
            {
                var fromAddress = new MailAddress(Properties.Settings.Default.MailUserName, "BuildingTomorrow House");
                var toAddresses = Properties.Settings.Default.DefaultProblemMails.Cast<string>().Select(tad => new MailAddress(tad, "Admin"));
                string fromPassword = Properties.Settings.Default.MailPassword;
                string subject = "Important Error Message";
                string body = string.Format("Catched Error: \r\n MethodName: {0}\r\n File: {1}\r\n Line:{2} \r\n Exception: {3} \r\n Notes: {4}", memberName, filePath, lineNumber, exceptionName, Mailmessage);

                var smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",
                    Port = 587,
                    EnableSsl = true,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
                };
                foreach (var addr in toAddresses)
                {
                    using (var message = new MailMessage(fromAddress, addr)
                    {
                        Subject = subject,
                        Body = body
                    })
                    {
                        smtp.Send(message);
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> SendWarningSensorGroupMail(string Mailmessage, string sensorName, string uname)
        {
            try
            { // new MailAddress(Properties.Settings.Default.DefaultProblemMails, "Admin");
                var fromAddress = new MailAddress(Properties.Settings.Default.MailUserName, "BuildingTomorrow House");
                var toAddresses = Properties.Settings.Default.DefaultProblemMails.Cast<string>().Select(tad => new MailAddress(tad,"Admin"));
                string fromPassword = Properties.Settings.Default.MailPassword;
                string subject = "Important Warning Message";
                string body = string.Format(" Sensor Group Deletion was detected: \r\n Sensor Group Name: {0}\r\n Username who deleted the sensor group: {1}\r\n", sensorName, uname);

                var smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",
                    Port = 587,
                    EnableSsl = true,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
                };
                foreach (var addr in toAddresses)
                {
                using (var message = new MailMessage(fromAddress, addr)
                {
                    Subject = subject,
                    Body = body
                })
                {
                    smtp.Send(message);
                }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public async Task<bool> SendWarningSensorMail(string Mailmessage,string sensorName,string uname)
        {
            try
            {
                var fromAddress = new MailAddress(Properties.Settings.Default.MailUserName, "BuildingTomorrow House");
                var toAddresses = Properties.Settings.Default.DefaultProblemMails.Cast<string>().Select(tad => new MailAddress(tad, "Admin"));
                string fromPassword = Properties.Settings.Default.MailPassword;
                string subject = "Important Warning Message";
                string body = string.Format(" Sensor Deletion was detected: \r\n Sensor Name: {0}\r\n Username who deleted the sensor: {1}\r\n", sensorName, uname);

                var smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",
                    Port = 587,
                    EnableSsl = true,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
                };
                foreach (var addr in toAddresses)
                {
                    using (var message = new MailMessage(fromAddress, addr)
                    {
                        Subject = subject,
                        Body = body
                    })
                    {
                        smtp.Send(message);
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
